//@author A0097466M
#include "Parser.h"

const string Parser::ERRORMESSAGE_MISSING_BRACKET = "Format Invalid : Missing Bracket";
const string Parser::ERRORMESSAGE_INVALID_TIME = "Format Invalid : Invalid Time Format";
const string Parser::ERRORMESSAGE_INVALID_DATE = "Format Invalid : Invalid Date Format";
const string Parser::STRING_NEXT = "Next";
const string Parser::STRING_00 = "00";
const string Parser::STRING_12 = "12";
const string Parser::STRING_24 = "24";
const char Parser::CHARACTER_DOT = '.';
const char Parser::CHARACTER_BACK_SLASH = '/';

Parser::Parser(void){
}

int Parser::stringToInt(string inputString){
	int outputInt;
	istringstream outputStream(inputString);

	outputStream >> outputInt;

	return outputInt;
}

string Parser::intToString(int inputInt){

	stringstream outputStream;

	if(inputInt < 10){
		outputStream << '0' << inputInt;
	} else {
		outputStream << inputInt;
	}

	return outputStream.str();
}

string Parser::normalizeInvalidDate(string date){

	string day = date.substr(0,2);
	string month = date.substr(2,2);
	string year = date.substr(4,4);

	int maxDay = maxNumOfDays(month, year);
	int intDay = stringToInt(day);
	int intMonth = stringToInt(month);

	if(intDay > maxDay){
		intDay = intDay - maxDay;
		day = intToString(intDay);

		if(checkValidMonth(intToString(intMonth + 1))){
			month = intToString(intMonth + 1);
		} else {
			int intYear = stringToInt(year);

			year = intToString(intYear + 1);

			month = "01";
		}
	}

	return day + month + year;
}

bool Parser::compareTime(string time1, string time2){
	bool compareTime = false;
	string hour1 = time1.substr(0,2);
	string hour2 = time2.substr(0,2);

	if((stringToInt(hour1)) > (stringToInt(hour2))){
		compareTime = true;
	} else if((stringToInt(hour1)) == (stringToInt(hour2))){
		string min1 = time1.substr(2,2);	
		string min2 = time2.substr(2,2);
		if((stringToInt(min1)) >= (stringToInt(min2))){
			compareTime = true;
		}
	}
	return compareTime;
}

bool Parser::checkStringOfInt(string rawTime){
	bool stringOfInt = true;
	for(unsigned i=0;i<rawTime.size();i++){
		if((rawTime[i] < '0') || (rawTime[i] > '9')){
			stringOfInt = false;
		}
	}

	return stringOfInt;
}

bool Parser::checkStringOfChar(string rawDate){
	bool stringOfChar = true;

	for(unsigned i=0;i<rawDate.size();i++){
		if((rawDate[i] < 'A') || (rawDate[i] > 'z') || ((rawDate[i] >'Z') && (rawDate[i] < 'a'))){
			stringOfChar = false;
		}
	}

	return stringOfChar;

}

int Parser::numberOfGivenCharacter(string rawTime, char givenCharacter){
	int counter = 0;

	for(unsigned i = 0; i < (rawTime.size()); i++){
		if(rawTime[i] == givenCharacter){
			counter++;
		}
	}

	return counter;
}

int Parser::wordCount(string rawDate){
	string word;
	istringstream outputStream(rawDate);
	int counter = 0;

	while(outputStream >> word){
		counter++;
	}

	return counter;
}

void Parser::defaultMonthsInYear(vector<string>& monthsInYear){
	monthsInYear.push_back(Utilities::STRING_JAN);
	monthsInYear.push_back(Utilities::STRING_FEB);
	monthsInYear.push_back(Utilities::STRING_MAR);
	monthsInYear.push_back(Utilities::STRING_APR);
	monthsInYear.push_back(Utilities::STRING_MAY);
	monthsInYear.push_back(Utilities::STRING_JUN);
	monthsInYear.push_back(Utilities::STRING_JUL);
	monthsInYear.push_back(Utilities::STRING_AUG);
	monthsInYear.push_back(Utilities::STRING_SEP);
	monthsInYear.push_back(Utilities::STRING_OCT);
	monthsInYear.push_back(Utilities::STRING_NOV);
	monthsInYear.push_back(Utilities::STRING_DEC);
}

void Parser::defaultDaysInWeek(vector<string>& daysInWeek){
	daysInWeek.push_back(Utilities::STRING_SUN);
	daysInWeek.push_back(Utilities::STRING_MON);
	daysInWeek.push_back(Utilities::STRING_TUE);
	daysInWeek.push_back(Utilities::STRING_WED);
	daysInWeek.push_back(Utilities::STRING_THU);
	daysInWeek.push_back(Utilities::STRING_FRI);
	daysInWeek.push_back(Utilities::STRING_SAT);
	
}

Task Parser::parseTask(string taskInString){	
	vector<string> rawInputs;

	for(unsigned i = 0; i < 5; i++){
		if(taskInString.find_first_of(Utilities::STRING_BLOCK_OPEN) == -1){
			throw runtime_error(ERRORMESSAGE_MISSING_BRACKET);			
		} else {
			rawInputs.push_back(taskInString.substr(taskInString.find_first_of(Utilities::STRING_BLOCK_OPEN)+1, taskInString.find_first_of(Utilities::STRING_BLOCK_CLOSE)-1));
			taskInString = taskInString.substr(taskInString.find_first_of(Utilities::STRING_BLOCK_CLOSE) + 1);
		}
	}

	string description = rawInputs[0];
	string processedDate = processRawDate(rawInputs[1]);	
	string processedStartTime = processRawTime(rawInputs[2], true);	
	string processedEndTime = processRawTime(rawInputs[3], false);
	string tagDescription = rawInputs[4];
	processStartAndEndTime(processedStartTime, processedEndTime);

	return Task(description, processedDate, processedStartTime, processedEndTime, tagDescription);
}

void Parser::processStartAndEndTime(string startTime, string endTime){
	if(compareTime(startTime, endTime) || (startTime == endTime)){
		throw runtime_error(ERRORMESSAGE_INVALID_TIME);
	}
}


string Parser::processRawTime(string rawTime, bool startTime){
	string processedTime;

	if(timeTypeDefault(rawTime)){
		if(startTime){
			processedTime =  Utilities::STRING_DEFAULT_START_TIME_NUMERICAL;
		} else {
			processedTime =  Utilities::STRING_DEFAULT_END_TIME_NUMERICAL;
		}
	} else if(timeType1(rawTime)){
		processedTime = processTimeType1(rawTime);
	} else if(timeType2(rawTime)){
		processedTime = processTimeType2(rawTime);
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_TIME);
	}

	return processedTime;
}

bool Parser::timeTypeDefault(string rawTime){
	bool timeTypeDefault = false;

	if(rawTime == Utilities::STRING_DEFAULT_START_TIME || rawTime == Utilities::STRING_EMPTY || rawTime == Utilities::STRING_DEFAULT_END_TIME){
		timeTypeDefault = true;
	}

	return timeTypeDefault;
}


bool Parser::timeType1(string rawTime){
	bool timeType1 = false;
	if((rawTime.size() == 4) && (checkStringOfInt(rawTime))){
		timeType1 = true;
	}

	return timeType1;
}

bool Parser::timeType2(string rawTime){
	bool timeType2 = false;
	int length = rawTime.size();

	if(length == 3 || length == 4 || length == 6 || length ==7){
		if(!checkStringOfInt(rawTime) && !checkStringOfChar(rawTime)){
			timeType2 = true;
		}
	}

	return timeType2;
}

string Parser::processTimeType1(string rawTime){
	string processedTime;

	if(checkValidTime(rawTime)){
		processedTime = rawTime;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_TIME);
	}

	return processedTime;
}

string Parser::processTimeType2(string rawTime){
	string processedTime;

	string stringHour;
	string stringMin;
	int intHour = 0;

	intHour = intHour + processTimeNotation(rawTime);

	rawTime.pop_back();
	rawTime.pop_back();


	if((checkStringOfInt(rawTime)) && (numberOfGivenCharacter(rawTime, CHARACTER_DOT) == 0)){
		stringHour = rawTime;
		stringMin = STRING_00; 
	}

	if(numberOfGivenCharacter(rawTime, CHARACTER_DOT) == 1){
		stringMin = rawTime.substr(rawTime.find_first_of(CHARACTER_DOT)+1);

		while(rawTime[rawTime.size() - 1] != CHARACTER_DOT){
			rawTime.pop_back();
		}

		rawTime.pop_back();

		stringHour = rawTime;
	}

	if(stringHour == STRING_24)
	{
		stringHour = STRING_00;
	}

	intHour = intHour + stringToInt(stringHour);
	stringHour = intToString(intHour);

	if(checkValidTime(stringHour + stringMin)){
		processedTime = stringHour + stringMin;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_TIME);
	}

	return processedTime;
}

bool Parser::checkValidTime(string processedTime){
	bool validTime = false;

	string stringHour = processedTime.substr(0,2);
	string stringMin = processedTime.substr(2,2);

	int intHour = stringToInt(stringHour);
	int intMin = stringToInt(stringMin);

	if((intHour <= 23) && (intHour >= 0) && (intMin >= 0) && (intMin <= 59)){
		validTime = true;
	}

	return validTime;	
}


int Parser::processTimeNotation(string rawTime){
	string timeNotation;
	int intHour = -1;

	timeNotation = rawTime.substr(rawTime.size() - 2);
	Utilities::toUpperCase(timeNotation);

	if(timeNotation == Utilities::STRING_PM && ((rawTime.substr(0,2)) == STRING_12)){
		intHour = 0;
	} else if(timeNotation == Utilities::STRING_PM) {
		intHour = 12;
	} else if(timeNotation == Utilities::STRING_NN){
		intHour = 0;
	} else if(timeNotation == Utilities::STRING_MN){
		intHour = -12;
	} else if((timeNotation == Utilities::STRING_AM) && ((rawTime.substr(0,2)) == STRING_12)){
		intHour =  -12;
	} else if(timeNotation == Utilities::STRING_AM){
		intHour = 0;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_TIME);
	}

	return intHour;
}

string Parser::processRawDate(string rawDate){
	string processedDate;

	if(dateType1(rawDate)){
		processedDate = processDateType1(rawDate);
	} else if(dateType2(rawDate)){
		processedDate = processDateType2(rawDate);
	} else	if(dateType3(rawDate)){
		processedDate = processDateType3(rawDate);
	} else if(dateType4(rawDate)){
		processedDate = processDateType4(rawDate);
	}else throw runtime_error(ERRORMESSAGE_INVALID_DATE);

	return processedDate;
}

bool Parser::dateType1(string rawDate){
	bool dateType1 = false;
	if(((rawDate.size()) == 8) && (checkStringOfInt(rawDate))){
		dateType1 = true;
	}

	return dateType1;
}

bool Parser::dateType2(string rawDate){
	bool dateType2 = false;

	if(wordCount(rawDate) == 2){
		string word1, word2;
		istringstream outputStream(rawDate);

		outputStream>>word1;
		outputStream>>word2;

		if(checkStringOfInt(word1) && checkStringOfChar(word2)){
			dateType2 = true;
		}
	}

	if(wordCount(rawDate) == 3){
		string word1, word2, word3;
		istringstream outputStream(rawDate);

		outputStream>>word1;
		outputStream>>word2;
		outputStream>>word3;

		if(checkStringOfInt(word1) && checkStringOfChar(word2) && checkStringOfInt(word3)){
			dateType2 = true;
		}
	}

	return dateType2;
}

bool Parser::dateType3(string rawDate){
	bool dateType3 = false;

	if((numberOfGivenCharacter(rawDate, CHARACTER_BACK_SLASH) == 1) || (numberOfGivenCharacter(rawDate, CHARACTER_BACK_SLASH) == 2)){
		dateType3 = true;
	}

	return dateType3;
}

bool Parser::dateType4(string rawDate){
	bool dateType4 = false;

	if(wordCount(rawDate) == 1){
		if(checkStringOfChar(rawDate)){
			dateType4 = true;
		}
	}

	if(wordCount(rawDate) == 2){
		string word1, word2;
		istringstream outputStream(rawDate);

		outputStream>>word1;
		outputStream>>word2;

		if(checkStringOfChar(word1) && checkStringOfChar(word2)){
			dateType4 = true;
		}
	}

	return dateType4;
}

string Parser::processDateType1(string rawDate){
	string processDate;
	if(checkValidDate(rawDate)){
		processDate = rawDate;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processDate;
}

string Parser::processDateType2(string rawDate){
	string processedDate;

	if(wordCount(rawDate) == 2){
		processedDate = processType2DateWithoutYear(rawDate);
	} else if(wordCount(rawDate) == 3){
		processedDate = processType2DateWithYear(rawDate);
	} else{
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processedDate;
}

string Parser::processType2DateWithYear(string rawDate){
	istringstream streamDate(rawDate);
	string processedDate;
	string day, month, year;

	streamDate >> day;
	streamDate >> month;
	streamDate >> year;

	if(!(checkStringOfInt(day)) && !(checkStringOfChar(month)) && !(checkStringOfInt(year))){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	if(day.size() == 1){
		int intDay = stringToInt(day);
		day = intToString(intDay);
	}

	month = convertMonth(month);

	if((checkValidYear(year)) && (checkValidDay(day, month, year))){
		processedDate = day + month + year;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processedDate;
}

string Parser::processType2DateWithoutYear(string rawDate){
	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%d%m%Y",localtime(&t) );  
	string today(tmp);

	istringstream streamDate(rawDate);
	string processedDate;
	string day, month, year;

	streamDate >> day;
	streamDate >> month;
	year = today.substr(4); 

	if(!(checkStringOfInt(day)) && !(checkStringOfChar(month))){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}
	if(day.size() == 1){
		int intDay = stringToInt(day);
		day = intToString(intDay);
	}

	month = convertMonth(month);

	if(checkValidDay(day, month, year)){
		processedDate = day + month + year;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processedDate;
}

string Parser::processDateType3(string rawDate){
	string processedDate;

	if(numberOfGivenCharacter(rawDate,CHARACTER_BACK_SLASH) == 1){
		processedDate = processType3DateWithoutYear(rawDate);
	}	

	if(numberOfGivenCharacter(rawDate,CHARACTER_BACK_SLASH) == 2){
		processedDate = processType3DateWithYear(rawDate);
	}	

	return processedDate;
}

string  Parser::processType3DateWithoutYear(string rawDate){	
	string processedDate;
	string day;
	string month;
	string year;

	day = rawDate.substr(0, rawDate.find_first_of(CHARACTER_BACK_SLASH));

	if(rawDate.find_first_of(CHARACTER_BACK_SLASH) == (rawDate.size() - 1)){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	month = rawDate.substr(rawDate.find_first_of(CHARACTER_BACK_SLASH) + 1);


	if(!(checkStringOfInt(day)) || (!(checkStringOfInt(month)))){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%d%m%Y",localtime(&t) );  
	string today(tmp);
	year = today.substr(4); 


	if(day.size() == 1){
		int intDay = stringToInt(day);
		day = intToString(intDay);
	}

	if(month.size() == 1){
		int intMonth = stringToInt(month);
		month = intToString(intMonth);
	}

	if((checkValidMonth(month)) && (checkValidDay(day, month, year))){
		processedDate = day + month + year;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processedDate;
}

string Parser::processType3DateWithYear(string rawDate){
	string processedDate;
	string day;
	string month;
	string year;

	day = rawDate.substr(0, rawDate.find_first_of(CHARACTER_BACK_SLASH));
	rawDate = rawDate.substr(rawDate.find_first_of(CHARACTER_BACK_SLASH) + 1);
	month = rawDate.substr(0, rawDate.find_first_of(CHARACTER_BACK_SLASH));

	if(rawDate.find_first_of(CHARACTER_BACK_SLASH) == (rawDate.size())){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	year = rawDate.substr(rawDate.find_first_of(CHARACTER_BACK_SLASH) + 1);

	if(!(checkStringOfInt(day)) && !(checkStringOfInt(month)) && !(checkStringOfInt(year))){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	if(day.size() == 1){
		int intDay = stringToInt(day);
		day = intToString(intDay);
	}

	if(month.size() == 1){
		int intMonth = stringToInt(month);
		month = intToString(intMonth);
	}

	if((checkValidMonth(month)) && (checkValidYear(year)) && (checkValidDay(day, month, year))){
		processedDate = day + month + year;
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	return processedDate;
}

string Parser::processDateType4(string rawDate){
	string processedDate;

	if(wordCount(rawDate) == 1){
		processedDate = dateType4SingleWord(rawDate);
	}

	if(wordCount(rawDate) == 2){
		processedDate = dateType4DoubleWord(rawDate);
	}

	return processedDate;
}

string Parser::dateType4SingleWord(string rawDate){
	string processedDate;
	bool withNext = false;

	Utilities::toLowerCase(rawDate);

	if((rawDate == Utilities::STRING_TODAY) || (rawDate == Utilities::STRING_DEFAULT_DATE)){
		processedDate = processToday();
	} else if(rawDate == Utilities::STRING_TOMORROW){
		processedDate = processTomorrow();
	} else {
		processedDate = processDay(rawDate, withNext);
	}

	if(!checkValidDate(processedDate)){
		processedDate = normalizeInvalidDate(processedDate);
	}

	return processedDate;
}


string Parser::dateType4DoubleWord(string rawDate){
	string processedDate;
	istringstream outputStream(rawDate);
	string word1, word2;
	bool withNext = false;

	outputStream >> word1;
	outputStream >> word2;

	Utilities::toStandardCase(word1);
	Utilities::toStandardCase(word2);	

	if(word1 != STRING_NEXT){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	} else {
		withNext = true;
		processedDate = processDay(word2, withNext);
	}

	if(!checkValidDate(processedDate)){
		processedDate = normalizeInvalidDate(processedDate);
	}

	return processedDate;
}


string Parser::processToday(){
	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%d%m%Y",localtime(&t) );  
	string today(tmp);

	return today;
}

string Parser::processTomorrow(){
	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%d%m%Y",localtime(&t) );  
	string today(tmp);

	string day = today.substr(0,2);
	string monthYear = today.substr(2,6);

	int intDay = stringToInt(day);
	intDay++;
	day = intToString(intDay);

	return day + monthYear;
}
string Parser::processDay(string rawDate, bool withNext){
	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%d%m%Y",localtime(&t) );  
	string today(tmp);

	string day = today.substr(0,2);
	string monthYear = today.substr(2,6);
	int intDay = stringToInt(day);

	if(withNext){
		intDay = intDay + diffInDaysWithNext(rawDate);
	} else {
		intDay = intDay + diffInDaysWithoutNext(rawDate);
	}

	day = intToString(intDay);

	return day + monthYear;
}

int Parser::diffInDaysWithNext(string taskDay){
	vector<string> daysInWeek;

	defaultDaysInWeek(daysInWeek);

	int diff = -1;
	int intCurrentDay = -1;
	int intTaskDay = -1;
	bool taskDayFound = false;

	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%a",localtime(&t) );  
	string currentDay(tmp);

	taskDay = taskDay.substr(0,3);

	Utilities::toStandardCase(taskDay);

	for(unsigned i = 0; i < 7; i++){
		if(daysInWeek[i] == currentDay){
			intCurrentDay = i;
		}

		if(daysInWeek[i] == taskDay){
			intTaskDay = i;
			taskDayFound = true;
		}
	}

	if(taskDayFound == false){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	if(intTaskDay <= intCurrentDay)	{
		diff = 7 - (intCurrentDay - intTaskDay);
	} else {
		diff = 7 + (intTaskDay - intCurrentDay);
	}

	return diff;
}

int Parser::diffInDaysWithoutNext(string taskDay){
	vector<string> daysInWeek;

	defaultDaysInWeek(daysInWeek);

	int diff = -1;
	int intCurrentDay = -1;
	int intTaskDay = -1;
	bool taskDayFound = false;

	time_t t = time(0); 
	char tmp[64]; 
	strftime( tmp, sizeof(tmp), "%a",localtime(&t) );  
	string currentDay(tmp);

	taskDay = taskDay.substr(0,3);
	Utilities::toStandardCase(taskDay);

	for(unsigned i = 0; i < 7; i++){
		if(daysInWeek[i] == currentDay){
			intCurrentDay = i;
		}

		if(daysInWeek[i] == taskDay){
			intTaskDay = i;
			taskDayFound = true;
		}
	}

	if(taskDayFound == false){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	if(intTaskDay > intCurrentDay){
		diff = intTaskDay - intCurrentDay;
	} else {
		diff = 7 - (intCurrentDay - intTaskDay);
	}

	return diff;
}

string Parser::convertMonth(string month){
	if(checkStringOfChar(month)){
		month = month.substr(0,3);

		Utilities::toStandardCase(month);
	} else {
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	int intMonth = -1;
	string stringMonth;
	vector<string> monthsInYear;

	defaultMonthsInYear(monthsInYear);

	for(unsigned i = 0; i < 12; i++){
		if(month == monthsInYear[i]){
			intMonth = i + 1;
		}
	}

	if(intMonth == -1){
		throw runtime_error(ERRORMESSAGE_INVALID_DATE);
	}

	stringMonth = intToString(intMonth);

	return stringMonth;	
}

bool Parser::checkValidDate(string rawDate){
	string day, month, year;
	bool validDate = false;

	year = rawDate.substr(4);
	month = rawDate.substr(2,2);
	day = rawDate.substr(0,2);

	if((checkValidYear(year)) && (checkValidMonth(month)) && (checkValidDay(day,month,year))){
		validDate = true;
	}

	return validDate;
}

bool Parser::checkValidYear(string year){
	bool validYear = false;

	if(year.size() == 4){
		validYear = true;
	}

	return validYear;
}

bool Parser::checkValidMonth(string month){
	bool validMonth = false;
	int intMonth = stringToInt(month);

	if(month.size() == 2){
		if((intMonth <= 12) && (intMonth >= 1)){
			validMonth = true;
		}
	}

	return validMonth;
}

bool Parser::checkValidDay(string day, string month, string year){
	bool validDay = false;
	int max = maxNumOfDays(month, year);
	int intDay = stringToInt(day);

	if(day.size() == 2){
		if((intDay >= 1) && (intDay <= max)){
			validDay = true;
		}
	}

	return validDay;
}

int Parser::maxNumOfDays(string month, string year){
	int maxDays = -1;
	int intMonth = stringToInt(month);

	if((intMonth <= 7) && ((intMonth % 2) == 1)){
		maxDays = 31;
	}

	if(intMonth >= 8){
		if((intMonth % 2) == 0){
			maxDays = 31;
		} else {
			maxDays = 30;
		}
	}

	if(intMonth == 2){
		if(checkLeapYear(year)){
			maxDays = 29;
		} else {
			maxDays = 28;
		}
	}

	if((intMonth == 4) || (intMonth == 6)){
		maxDays = 30;
	}

	return maxDays;
}

bool Parser::checkLeapYear(string year){
	bool leapYear = false;
	int intYear = stringToInt(year);

	if((intYear % 400) == 0){
		leapYear = true;
	} else if((intYear % 100) == 0){
		leapYear = false;
	} else if((intYear % 4) == 0){
		leapYear = true;
	}

	return leapYear;
}
string Parser::reverseParse(Task incomingTask){
	string returnCommand;

	returnCommand =  taskExtractDescription(incomingTask) + taskExtractDate(incomingTask) + taskExtractTime1(incomingTask) +taskExtractTime2(incomingTask) +taskExtractTag(incomingTask);

	return returnCommand;
}

string Parser::taskExtractDate(Task incomingTask){
	string Date;

	Date = Utilities::STRING_BLOCK_OPEN + incomingTask.getDate() + Utilities::STRING_BLOCK_CLOSE;

	return Date;
}

string Parser::taskExtractTime1(Task incomingTask){
	string Time;

	Time = incomingTask.getStartTime();

	if(Time.size() > 0){
		Time = Utilities::STRING_BLOCK_OPEN + Time + Utilities::STRING_BLOCK_CLOSE;
	} else {
		Time = Utilities::STRING_BLOCK_OPEN + Utilities::STRING_DEFAULT_START_TIME + Utilities::STRING_BLOCK_CLOSE;
	}

	return Time;
}

string Parser::taskExtractTime2(Task incomingTask){
	string Time;

	Time = incomingTask.getEndTime();

	if(Time.size() > 0){
		Time = Utilities::STRING_BLOCK_OPEN + Time + Utilities::STRING_BLOCK_CLOSE;
	} else {
		Time = Utilities::STRING_BLOCK_OPEN + Utilities::STRING_DEFAULT_END_TIME + Utilities::STRING_BLOCK_CLOSE;
	}

	return Time;
}
string Parser::taskExtractDescription(Task incomingTask){
	string Description;

	Description = Utilities::STRING_BLOCK_OPEN + incomingTask.getDescription() + Utilities::STRING_BLOCK_CLOSE;

	return Description;
}

string Parser::taskExtractTag(Task incomingTask){
	string tag;

	tag = Utilities::STRING_BLOCK_OPEN + incomingTask.getTag() + Utilities::STRING_BLOCK_CLOSE;

	return tag;
}

